package edu.njit.hz278.controller.patient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import edu.njit.hz278.bean.Allergy;
import edu.njit.hz278.bean.ConsultationHistoryOfPatient;
import edu.njit.hz278.bean.MedicalData;
import edu.njit.hz278.bean.NestedConsultationHistoryOfPatient;
import edu.njit.hz278.bean.Patient;
import edu.njit.hz278.controller.Constants;
import edu.njit.hz278.core.db.IQuery;
import edu.njit.hz278.core.db.Query;
import edu.njit.hz278.core.web.Get;
import edu.njit.hz278.core.web.ModelView;
import edu.njit.hz278.core.web.Param;

/**
 * 
 * @author Rivers Zhang
 * 
 */
public class View {

	private static final IQuery<Patient> queryForPatient = new Query<>(
			Patient.class);
	private static final IQuery<MedicalData> queryForMedicalData = new Query<>(
			MedicalData.class);
	private static final IQuery<Allergy> queryForAllergy = new Query<>(
			Allergy.class);
	private static final IQuery<ConsultationHistoryOfPatient> queryForHistory = new Query<>(
			ConsultationHistoryOfPatient.class);

	/**
	 * Returns all patients.
	 * 
	 * @param page
	 * @return
	 */
	@Get
	public List<Patient> all(@Param("page") int page) {
		return queryForPatient.list(page, Constants.DEFAULT_PAGE_SIZE);
	}

	/**
	 * Returns the personal information, medical data and allergies of the
	 * patient.
	 * 
	 * @param pNum
	 * @param mv
	 * @return
	 */
	@Get
	public ModelView patient(@Param("pNum") int pNum, ModelView mv) {
		Patient patient = queryForPatient.getByKey("pNum", pNum);
		if ((pNum = patient.getpNum()) != 0) {
			StringBuilder sql = new StringBuilder();
			sql.append(
					"SELECT code, description FROM patient_has_allergy pha, allergy a ")
					.append(" WHERE pha.pNum = ? AND pha.allergyCode = a.code");
			mv.put("patient", patient);
			mv.put("medicalData", queryForMedicalData.get("pNum", pNum));
			mv.put("allergy", queryForAllergy.getBySQL(sql.toString(), pNum));
		}

		return mv;
	}

	/**
	 * Returns an unsorted list of diagnosis and illness history of patient
	 * 
	 * @pNum.
	 * 
	 * @param pNum
	 * @return an unsorted list of diagnosis and illness history.
	 */
	@Get
	public List<NestedConsultationHistoryOfPatient> patientDiag(
			@Param("pNum") int pNum) {
		StringBuilder sql = new StringBuilder();
		sql.append(
				"SELECT * FROM consultation c, employee e, diagnosis d, illness i ")
				.append("WHERE c.pNum = ? AND d.pNum = ? AND ")
				.append("c.empid = e.empid AND d.date = c.date AND i.code = d.illnessCode");

		List<ConsultationHistoryOfPatient> list = queryForHistory.getBySQL(
				sql.toString(), pNum, pNum);

		/**
		 * clustering on physician and date.
		 */
		Map<String, NestedConsultationHistoryOfPatient> groupByPhysAndDate = new HashMap<String, NestedConsultationHistoryOfPatient>();

		for (ConsultationHistoryOfPatient chp : list) {
			String key = chp.getPhysNameAndDate();
			NestedConsultationHistoryOfPatient value;
			if ((value = groupByPhysAndDate.get(key)) != null)
				value.addDiagnosis(chp.getComment(), chp.getDescription(),
						chp.getIllnessCode());
			else {
				value = new NestedConsultationHistoryOfPatient(chp.getName(),
						chp.getEmpid(), chp.getDate(), chp.getComment());
				value.addDiagnosis(chp.getComment(), chp.getDescription(),
						chp.getIllnessCode());
				groupByPhysAndDate.put(key, value);
			}
		}

		return new ArrayList<>(groupByPhysAndDate.values());
	}
}
